package com.astar.shiro;

import com.astar.entity.User;
import com.astar.mapper.UserMapper;
import com.astar.service.IUserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.Set;

public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private IUserService userService;
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行授权逻辑");
        //1.从PrincipalCollection中获取登录用户的信息
        Object principal = principalCollection.getPrimaryPrincipal();
        //2.利用登录的用户的信息来获取当前用户的角色或权限（两种： 1.信息中已经包含了角色和权限信息  2.在这里从数据库中查询
        Set<String> perms = userService.selectPerms(principal.toString());
        //3.创建SimpleAuthorizationInfo，并设置roles属性//给资源进行授权
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo ();
        info.setStringPermissions(perms);
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1.把AuthenticationToken转换为 UsernamePasswordToken
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken)authenticationToken;

        //2.从 UsernamePasswordToken 获取username得到用户名
        String username = usernamePasswordToken.getUsername();
        char[] password = usernamePasswordToken.getPassword();
        //3.调用数据库的方法从数据库中查询userName对应账户信息
        //数据库中存的用户名密码
        User user = userMapper.selectUserForUserName(username);
        //4.若用户不存在，则可以抛出其他异常
        if (user==null || user.equals("")){
            throw new UnknownAccountException("用户不存在");
        }
        //5.根据用户信息的情况，决定是否要抛出其他异常
        if (!"0".equals(user.getStatus())){
            throw new LockedAccountException("账户被锁定");
        }
        //6.根据用户信息，来构建 AuthenticationInfo 对象并返回,shiro会帮我们做密码比对，
        // 通常使用的实现类为 SimpleAuthenticationInfo
        //参数说明
        //参数一： principal ：认证的实体信息，可以是username，也可以是User对象，也可以是自己定义的用户信息对象
        //参数二：credentials: 密码
        ////参数三： credentialsSalt  盐值   使用 ByteSource.Util.bytes()计算盐值 ，参数是随机盐，也可以使用账号作为盐
        //参数四： realmName: 当前realm对象的name，调用父类的getName方法即可

        System.out.println("执行登录认证逻辑");
        ByteSource salt = ByteSource.Util.bytes(user.getSalt());
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,user.getPassword(),salt,getName());
        return simpleAuthenticationInfo;

    }

    public static void main(String[] args) {
        String salt = "111111";
        String password = "111111";
        int number = 16;
        SimpleHash simpleHash = new SimpleHash("MD5",password,salt,number);
        System.out.println(simpleHash.toString());
    }
}
